package com.huan.springboot.websocket;

import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;
import org.yeauty.annotation.*;
import org.yeauty.pojo.Session;

import java.util.UUID;

/**
 * 1、如果path=/ws/{user} 则可以使用 @PathVariable 来获取
 * 2、<a href="https://gitee.com/Yeauty/netty-websocket-spring-boot-starter">https://gitee.com/Yeauty/netty-websocket-spring-boot-starter</a>
 *
 * @author huan.fu
 * @date 2022/4/26 - 14:05
 */
@ServerEndpoint(path = "${ws.path}", host = "${ws.host}", port = "${ws.port}",
        bossLoopGroupThreads = "${ws.boss-loop-group-threads}", workerLoopGroupThreads = "${ws.worker-loop-group-threads}")
public class WebsocketHandler {

    @Autowired
    private WebsocketSessionRepository websocketSessionRepository;

    private static final Logger log = LoggerFactory.getLogger(WebsocketHandler.class);

    /**
     * 当有新的连接进入时，对该方法进行回调
     */
    @BeforeHandshake
    public void handshake(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap) {
        session.setSubprotocols("stomp");
        log.info("握手阶段...");
        //        if (!"ok".equals(req)) {
        //            log.info("Authentication failed!");
        //            session.close();
        //        }
        String userId = UUID.randomUUID().toString();
        log.info("产生一个userId:[{}]", userId);
        session.setAttribute("userId", userId);
    }

    /**
     * 当有新的WebSocket连接完成时，对该方法进行回调
     */
    @OnOpen
    public void onOpen(Session session, HttpHeaders headers, @RequestParam String req, @RequestParam MultiValueMap reqMap) {
        log.info("连接打开session:{}", session.hashCode());

        websocketSessionRepository.addSession(session);
    }

    /**
     * 当有WebSocket连接关闭时，对该方法进行回调
     */
    @OnClose
    public void onClose(Session session) {
        log.info("连接关闭session:{}", session.hashCode());
        session.close().addListener((ChannelFutureListener) channelFuture -> log.info("关闭成功"));
    }

    /**
     * 当有WebSocket抛出异常时，对该方法进行回调
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        log.info("发生了错误", throwable);
    }

    /**
     * 当接收到字符串消息时，对该方法进行回调
     */
    @OnMessage
    public void onMessage(Session session, String message) {
        log.info("session:{} 收到了消息: {}", session.hashCode(), message);

        session.sendText("服务器返回消息:" + message);
    }

    /**
     * 当接收到二进制消息时，对该方法进行回调
     */
    @OnBinary
    public void onBinary(Session session, byte[] bytes) {
        log.info("获取到了二进制消息");
        for (byte b : bytes) {
            log.info("{}", b);
        }
        session.sendBinary(bytes);
    }

    /**
     * 当接收到Netty的事件时，对该方法进行回调
     */
    @OnEvent
    public void onEvent(Session session, Object evt) {
        log.info("接收到了事件");
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            switch (idleStateEvent.state()) {
                case READER_IDLE:
                    log.info("read idle");
                    break;
                case WRITER_IDLE:
                    log.info("write idle");
                    break;
                case ALL_IDLE:
                    log.info("all idle");
                    break;
                default:
                    break;
            }
        }
    }
}



